home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / infosrvr / dev / www_talk.930 / 001258_daemon _Sat Jun 12 03:00:02 1993.msg < prev    next >
Internet Message Format  |  1994-01-24  |  13KB

  1. Received: by  nxoc01.cern.ch  (NeXT-1.0 (From Sendmail 5.52)/NeXT-2.0)
  2.     id AA05957; Sat, 12 Jun 93 03:00:09 MET DST
  3. Return-Path: <janssen@parc.xerox.com>
  4. Received: from dxmint.cern.ch by  nxoc01.cern.ch  (NeXT-1.0 (From Sendmail 5.52)/NeXT-2.0)
  5.     id AA05951; Sat, 12 Jun 93 03:00:02 MET DST
  6. Received: from alpha.Xerox.COM by dxmint.cern.ch (5.65/DEC-Ultrix/4.3)
  7.     id AA15780; Sat, 12 Jun 1993 03:22:01 +0200
  8. Received: from holmes.parc.xerox.com ([13.1.100.162]) by alpha.xerox.com with SMTP id <11849>; Fri, 11 Jun 1993 18:21:39 PDT
  9. Received: by holmes.parc.xerox.com id <16134>; Fri, 11 Jun 1993 18:21:34 -0700
  10. Received: from Messages.7.15.N.CUILIB.3.45.SNAP.NOT.LINKED.holmes.parc.xerox.com.sun4.41
  11.           via MS.5.6.holmes.parc.xerox.com.sun4_41;
  12.           Fri, 11 Jun 1993 18:21:21 -0700 (PDT)
  13. Message-Id: <Eg6GyF0B0KGW9gefwF@holmes.parc.xerox.com>
  14. Date:     Fri, 11 Jun 1993 18:21:21 PDT
  15. Sender: Bill Janssen <janssen@parc.xerox.com>
  16. From: Bill Janssen <janssen@parc.xerox.com>
  17. To: timbl@www3.cern.ch, Bill Janssen <janssen@parc.xerox.com>
  18. Subject: Re: CR not stripped properly on FTP transfers
  19. Cc: www-talk@nxoc01.cern.ch
  20. In-Reply-To: <0g6Fu48B0KGW5geexr@holmes.parc.xerox.com>
  21. References: <0g6Fu48B0KGW5geexr@holmes.parc.xerox.com>
  22.  
  23. Yes, changing HTFTP to use image mode for transfers seems to work well. 
  24. Now tar file transfers work OK with -source.
  25.  
  26. But note that this quick (and dirty) fix has its own problems.  In
  27. particular, if I fetch a text file from a Mac FTP server (or any ftp
  28. server that doesn't use LF in its new-line string), the file will
  29. contain CR where there should be LF.  It's a shame we don't have two
  30. different URL schemes for FTP:  one (say binaryftp:foo) would be for
  31. binary documents, and the other (say, textftp:foo) would be for text
  32. documents.
  33.  
  34. Here's my version of HTFTP.c/HTFTPLoad() [note that it also has patches
  35. for our Internet gateway scheme, please ignore them]:
  36.  
  37. /*    Retrieve File from Server
  38. **    -------------------------
  39. **
  40. ** On entry,
  41. **    name        WWW address of a file: document, including hostname
  42. ** On exit,
  43. **    returns        Socket number for file if good.
  44. **            <0 if bad.
  45. */
  46. PUBLIC int HTFTPLoad
  47. ARGS4 (
  48.   CONST char *,            name,
  49.   HTParentAnchor *,        anchor,
  50.   HTFormat,            format_out,
  51.   HTStream *,            sink
  52. )
  53. {
  54.     BOOL isDirectory = NO;
  55.     int status;
  56.     int retry;            /* How many times tried? */
  57.     HTFormat format;
  58.     int transferType;
  59. #define    ASCIITransferType    1
  60. #define IMAGETransferType    2
  61.     
  62.     for (retry=0; retry<2; retry++) {    /* For timed out/broken connections */
  63.     
  64.     status = get_connection(name);
  65.     if (status<0) return status;
  66.  
  67. #ifdef LISTEN
  68.     status = get_listen_socket();
  69.     if (status<0) return status;
  70.     
  71. #ifdef REPEAT_PORT
  72. /*    Inform the server of the port number we will listen on
  73. */
  74.     {
  75.         status = response(port_command);
  76.         if (status !=2) {        /* Could have timed out */
  77.         if (status<0) continue;        /* try again - net error*/
  78.         return -status;            /* bad reply */
  79.         }
  80.         if (TRACE) fprintf(stderr, "FTP: Port defined.\n");
  81.     }
  82. #endif
  83. #else    /* Use PASV */
  84. /*    Tell the server to be passive
  85. */
  86.     {
  87.         char *p;
  88.         int reply, h0, h1, h2, h3, p0, p1;    /* Parts of reply */
  89.         status = response("PASV%c%c", CR, LF);
  90.         if (status !=2) {
  91.         if (status<0) continue;        /* retry or Bad return */
  92.         return -status;            /* bad reply */
  93.         }
  94.         for(p=response_text; *p; p++)
  95.         if ((*p<'0')||(*p>'9')) *p = ' ';    /* Keep only digits */
  96.         status = sscanf(response_text, "%d%d%d%d%d%d%d",
  97.             &reply, &h0, &h1, &h2, &h3, &p0, &p1);
  98.         if (status<5) {
  99.         if (TRACE) fprintf(stderr, "FTP: PASV reply has no inet address!\n");
  100.         return -99;
  101.         }
  102.         passive_port = (p0<<8) + p1;
  103.         if (TRACE) fprintf(stderr, "FTP: Server is listening on port %d\n",
  104.             passive_port);
  105.     }
  106.  
  107. /*    Open connection for data:
  108. */
  109.     {
  110.         struct sockaddr_in soc_address;
  111.         int status = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  112.         if (status<0) {
  113.         (void) HTInetStatus("socket for data socket");
  114.         return status;
  115.         }
  116.         data_soc = status;
  117.         
  118. #ifdef IGATEWAY
  119.         Cannot use PASV with IGATEWAY with this code as written
  120. #endif
  121.         soc_address.sin_addr.s_addr = control->addr;
  122.         soc_address.sin_port = htons(passive_port);
  123.         soc_address.sin_family = AF_INET;        /* Family, host order  */
  124.         if (TRACE) fprintf(stderr,  
  125.         "FTP: Data remote address is port %d, inet %d.%d.%d.%d\n",
  126.             (unsigned int)ntohs(soc_address.sin_port),
  127.             (int)*((unsigned char *)(&soc_address.sin_addr)+0),
  128.             (int)*((unsigned char *)(&soc_address.sin_addr)+1),
  129.             (int)*((unsigned char *)(&soc_address.sin_addr)+2),
  130.             (int)*((unsigned char *)(&soc_address.sin_addr)+3));
  131.     
  132.         status = connect(data_soc, (struct sockaddr*)&soc_address,
  133.             sizeof(soc_address));
  134.         if (status<0){
  135.         (void) HTInetStatus("connect for data");
  136.         NETCLOSE(data_soc);
  137.         return status;            /* Bad return */
  138.         }
  139.         
  140.         if (TRACE) fprintf(stderr, "FTP data connected, socket %d\n", data_soc);
  141.     }
  142. #endif /* use PASV */
  143.     status = 0;
  144.         break;    /* No more retries */
  145.  
  146.     } /* for retries */
  147.     if (status<0) return status;    /* Failed with this code */
  148.     
  149. /*    Ask for the file:
  150. */    
  151.     {
  152.         char *filename = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
  153.     char command[LINE_LENGTH+1];
  154.     int retrieveStatus;
  155.     
  156.     if (!*filename) StrAllocCopy(filename, "/");
  157.     sprintf(command, "TYPE I%c%c", CR, LF);
  158.     status = response(command);
  159.     if (status == 1)
  160.       transferType = IMAGETransferType;
  161.     else
  162.       transferType = ASCIITransferType;
  163.     sprintf(command, "RETR %s%c%c", filename, CR, LF);
  164.     format = HTFileFormat(filename);
  165.     status = response(command);
  166.     if (status != 1) {  /* Failed : try to CWD to it */
  167.       if (transferType == IMAGETransferType)
  168.         /* change back to ASCII */
  169.         {
  170.           sprintf(command, "TYPE A%c%c", CR, LF);
  171.           status = response(command);
  172.           transferType = ASCIITransferType;
  173.         }
  174.       sprintf(command, "CWD %s%c%c", filename, CR, LF);
  175.       status = response(command);
  176.       if (status == 2) {  /* Successed : let's NAME LIST it */
  177.         isDirectory = YES;
  178.         sprintf(command, "NLST%c%c", CR, LF);
  179.         status = response (command);
  180.       }
  181.     }
  182.     free(filename);
  183.     if (status != 1) return -status;        /* Action not started */
  184.     }
  185.  
  186. #ifdef LISTEN
  187. /*    Wait for the connection
  188. */
  189.     {
  190.     struct sockaddr_in soc_address;
  191.         int    soc_addrlen=sizeof(soc_address);
  192.     status = accept(master_socket,
  193.             (struct sockaddr *)&soc_address,
  194.             &soc_addrlen);
  195.     if (status<0)
  196.         return HTInetStatus("accept");
  197.     CTRACE(tfp, "TCP: Accepted new socket %d\n", status);
  198.     data_soc = status;
  199.     }
  200. #else
  201. /* @@ */
  202. #endif
  203.     if (isDirectory) {
  204.     return read_directory (anchor, name, format_out, sink);
  205.       /* returns HT_LOADED or error */
  206.     } else {
  207.     HTParseSocket(format, format_out,
  208.         anchor, data_soc, sink);
  209.  
  210.     HTInitInput(control->socket);
  211.     /* Reset buffering to control connection DD 921208 */
  212.     
  213.     status = NETCLOSE(data_soc);
  214.     if (TRACE) fprintf(stderr, "FTP: Closing data socket %d\n", data_soc);
  215.     if (status<0) (void) HTInetStatus("close");    /* Comment only */
  216.     data_soc = -1;    /* invalidate it */
  217.     
  218.     status = response(NIL);        /* Pick up final reply */
  219.     if (status!=2) return HTLoadError(sink, 500, response_text);
  220.  
  221.     if (transferType == IMAGETransferType)
  222.       /* change back to ASCII */
  223.       {
  224.         char command[10];
  225.  
  226.         sprintf(command, "TYPE A%c%c", CR, LF);
  227.         status = response(command);
  228.       }
  229.         
  230.     return HT_LOADED;
  231.     }       
  232. } /* open_file_read */
  233. /*    Retrieve File from Server
  234. **    -------------------------
  235. **
  236. ** On entry,
  237. **    name        WWW address of a file: document, including hostname
  238. ** On exit,
  239. **    returns        Socket number for file if good.
  240. **            <0 if bad.
  241. */
  242. PUBLIC int HTFTPLoad
  243. ARGS4 (
  244.   CONST char *,            name,
  245.   HTParentAnchor *,        anchor,
  246.   HTFormat,            format_out,
  247.   HTStream *,            sink
  248. )
  249. {
  250.     BOOL isDirectory = NO;
  251.     int status;
  252.     int retry;            /* How many times tried? */
  253.     HTFormat format;
  254.     int transferType;
  255. #define    ASCIITransferType    1
  256. #define IMAGETransferType    2
  257.     
  258.     for (retry=0; retry<2; retry++) {    /* For timed out/broken connections */
  259.     
  260.     status = get_connection(name);
  261.     if (status<0) return status;
  262.  
  263. #ifdef LISTEN
  264.     status = get_listen_socket();
  265.     if (status<0) return status;
  266.     
  267. #ifdef REPEAT_PORT
  268. /*    Inform the server of the port number we will listen on
  269. */
  270.     {
  271.         status = response(port_command);
  272.         if (status !=2) {        /* Could have timed out */
  273.         if (status<0) continue;        /* try again - net error*/
  274.         return -status;            /* bad reply */
  275.         }
  276.         if (TRACE) fprintf(stderr, "FTP: Port defined.\n");
  277.     }
  278. #endif
  279. #else    /* Use PASV */
  280. /*    Tell the server to be passive
  281. */
  282.     {
  283.         char *p;
  284.         int reply, h0, h1, h2, h3, p0, p1;    /* Parts of reply */
  285.         status = response("PASV%c%c", CR, LF);
  286.         if (status !=2) {
  287.         if (status<0) continue;        /* retry or Bad return */
  288.         return -status;            /* bad reply */
  289.         }
  290.         for(p=response_text; *p; p++)
  291.         if ((*p<'0')||(*p>'9')) *p = ' ';    /* Keep only digits */
  292.         status = sscanf(response_text, "%d%d%d%d%d%d%d",
  293.             &reply, &h0, &h1, &h2, &h3, &p0, &p1);
  294.         if (status<5) {
  295.         if (TRACE) fprintf(stderr, "FTP: PASV reply has no inet address!\n");
  296.         return -99;
  297.         }
  298.         passive_port = (p0<<8) + p1;
  299.         if (TRACE) fprintf(stderr, "FTP: Server is listening on port %d\n",
  300.             passive_port);
  301.     }
  302.  
  303. /*    Open connection for data:
  304. */
  305.     {
  306.         struct sockaddr_in soc_address;
  307.         int status = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  308.         if (status<0) {
  309.         (void) HTInetStatus("socket for data socket");
  310.         return status;
  311.         }
  312.         data_soc = status;
  313.         
  314. #ifdef IGATEWAY
  315.         Cannot use PASV with IGATEWAY with this code as written
  316. #endif
  317.         soc_address.sin_addr.s_addr = control->addr;
  318.         soc_address.sin_port = htons(passive_port);
  319.         soc_address.sin_family = AF_INET;        /* Family, host order  */
  320.         if (TRACE) fprintf(stderr,  
  321.         "FTP: Data remote address is port %d, inet %d.%d.%d.%d\n",
  322.             (unsigned int)ntohs(soc_address.sin_port),
  323.             (int)*((unsigned char *)(&soc_address.sin_addr)+0),
  324.             (int)*((unsigned char *)(&soc_address.sin_addr)+1),
  325.             (int)*((unsigned char *)(&soc_address.sin_addr)+2),
  326.             (int)*((unsigned char *)(&soc_address.sin_addr)+3));
  327.     
  328.         status = connect(data_soc, (struct sockaddr*)&soc_address,
  329.             sizeof(soc_address));
  330.         if (status<0){
  331.         (void) HTInetStatus("connect for data");
  332.         NETCLOSE(data_soc);
  333.         return status;            /* Bad return */
  334.         }
  335.         
  336.         if (TRACE) fprintf(stderr, "FTP data connected, socket %d\n", data_soc);
  337.     }
  338. #endif /* use PASV */
  339.     status = 0;
  340.         break;    /* No more retries */
  341.  
  342.     } /* for retries */
  343.     if (status<0) return status;    /* Failed with this code */
  344.     
  345. /*    Ask for the file:
  346. */    
  347.     {
  348.         char *filename = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
  349.     char command[LINE_LENGTH+1];
  350.     int retrieveStatus;
  351.     
  352.     if (!*filename) StrAllocCopy(filename, "/");
  353.     sprintf(command, "TYPE I%c%c", CR, LF);
  354.     status = response(command);
  355.     if (status == 1)
  356.       transferType = IMAGETransferType;
  357.     else
  358.       transferType = ASCIITransferType;
  359.     sprintf(command, "RETR %s%c%c", filename, CR, LF);
  360.     format = HTFileFormat(filename);
  361.     status = response(command);
  362.     if (status != 1) {  /* Failed : try to CWD to it */
  363.       if (transferType == IMAGETransferType)
  364.         /* change back to ASCII */
  365.         {
  366.           sprintf(command, "TYPE A%c%c", CR, LF);
  367.           status = response(command);
  368.           transferType = ASCIITransferType;
  369.         }
  370.       sprintf(command, "CWD %s%c%c", filename, CR, LF);
  371.       status = response(command);
  372.       if (status == 2) {  /* Successed : let's NAME LIST it */
  373.         isDirectory = YES;
  374.         sprintf(command, "NLST%c%c", CR, LF);
  375.         status = response (command);
  376.       }
  377.     }
  378.     free(filename);
  379.     if (status != 1) return -status;        /* Action not started */
  380.     }
  381.  
  382. #ifdef LISTEN
  383. /*    Wait for the connection
  384. */
  385.     {
  386.     struct sockaddr_in soc_address;
  387.         int    soc_addrlen=sizeof(soc_address);
  388.     status = accept(master_socket,
  389.             (struct sockaddr *)&soc_address,
  390.             &soc_addrlen);
  391.     if (status<0)
  392.         return HTInetStatus("accept");
  393.     CTRACE(tfp, "TCP: Accepted new socket %d\n", status);
  394.     data_soc = status;
  395.     }
  396. #else
  397. /* @@ */
  398. #endif
  399.     if (isDirectory) {
  400.     return read_directory (anchor, name, format_out, sink);
  401.       /* returns HT_LOADED or error */
  402.     } else {
  403.     HTParseSocket(format, format_out,
  404.         anchor, data_soc, sink);
  405.  
  406.     HTInitInput(control->socket);
  407.     /* Reset buffering to control connection DD 921208 */
  408.     
  409.     status = NETCLOSE(data_soc);
  410.     if (TRACE) fprintf(stderr, "FTP: Closing data socket %d\n", data_soc);
  411.     if (status<0) (void) HTInetStatus("close");    /* Comment only */
  412.     data_soc = -1;    /* invalidate it */
  413.     
  414.     status = response(NIL);        /* Pick up final reply */
  415.     if (status!=2) return HTLoadError(sink, 500, response_text);
  416.  
  417.     if (transferType == IMAGETransferType)
  418.       /* change back to ASCII */
  419.       {
  420.         char command[10];
  421.  
  422.         sprintf(command, "TYPE A%c%c", CR, LF);
  423.         status = response(command);
  424.       }
  425.         
  426.     return HT_LOADED;
  427.     }       
  428. } /* open_file_read */